#pragma once

#include "KNode.h"
#include "Regressor.h"

namespace kdtree
{

	class KDTree : public Regressor
{
public:
	KDTree(void);
	~KDTree(void);

	virtual void addPoint(Observation o, double target);					 //incremental learning
	virtual void addPoints(std::list< std::pair<Observation,double> >& l); //batch learning
	virtual void addPoints(list<Transition>& history, int actionIndex, int targetDim); 
	virtual bool predict(const Observation, double& result);				 //prediction (return false for I don't know)
	virtual double getConfidence(const Observation o); 

	void print(); 
	void setSplitCriterion(int v);
	void resetPoints(); 
	void setDimensionParameters(int dim, double_range_t* r);

public:
	//properties
	int	 dimension;		//dimension of input data
	double_range_t* ranges; 

	int		knownMinPoints;		//minimum number of points in a cell to make it known
	double	knownMaxLength;		//minimum length of each side of known cells (if bigger, it becomes unknown)
	double	maxAllowedError;	//minimum allowed error when adding a point to a known cell
	int		maxNumberOfSamples;	//maximum number of allowed samples in each cell (used with splitCriterion=SPLIT_USE_MAX_SAMPLES)
	KNode*	root;				//access to the root of the tree
	int		totalNodes;			//total number of nodes in this tree
	double eta; 

	int		splitCriterion;		//how do we decide to split a node (max number of samples, max allowed error)
	static const int SPLIT_USE_MAX_SAMPLES=1; 
	static const int SPLIT_USE_MAX_ALLOWED_ERROR=2; 
	static const int GENERALIZER_USE_MEAN=1; 
	static const int GENERALIZER_USE_LINEAR=2; 

	int		generalizerType;	//what kind of local generalizer is used for each cell 
};
}//namespace